/*
 * Classname ISSOService.java
 * 
 * Version Information
 * 
 * Date Feb 8, 2006
 *
 * Copyright (c) AmSoft Systems, 2006
 */
package net.amsoft.iservice.isso.service;

import java.util.Date;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;

import net.amsoft.iservice.isso.hibernate.Cookie;
import net.amsoft.iservice.isso.hibernate.IBroker;
import net.amsoft.iservice.isso.hibernate.Principal;
import net.amsoft.iservice.isso.hibernate.PrincipalMetaData;
import net.amsoft.iservice.isso.hibernate.Response;
import net.amsoft.iservice.isso.hibernate.Synonym;
import net.amsoft.iservice.isso.util.ISSOConstants;
import net.amsoft.iservice.isso.util.ISSOHelpers;
import net.amsoft.iservice.util.HibernateUtil;
import net.amsoft.iservice.util.IServiceUtil;
import net.amsoft.iservice.util.exception.IServiceException;
import net.amsoft.iservice.util.exception.IServiceSystemException;

import org.apache.log4j.Logger;
import org.hibernate.Session;
import org.hibernate.Transaction;

/**
 * ISSOService class is designed to perform the logic operations. It performs
 * different operations based on the requests from the application layer, these
 * operations are in terms of interacting with database(saving, retreiving,
 * updating data) using the ISSOHelpers class. Hence the class is a major
 * functional unit between application layer and the data (hibernate) layer. The
 * APIs provided in the ISSOService class are used in the application layer of
 * the ISSO Service.
 * 
 * @author mohit
 * @author jyoti
 * 
 */
public class ISSOService {
    private static Logger logger = Logger.getLogger(ISSOService.class);

    /**
     * Gets the principal object for the Activation token provided and returns
     * the Global I-Number, if the principal state is <B>Pending </B>
     * 
     * @param sActivationToken
     *            Activation token provided by user which is to be validated
     * @return Global I-Number correspondig to the activation token OR Null if
     *         activation token does is does not exist or the state of principal
     *         is NOT pending
     */
    public static String getGlobalINumber(String sActivationToken,
            String sGlobalINumber) {
        logger.info("getGlobalINumber() entry with token=" + sActivationToken
                + ",GIN=" + sGlobalINumber);
        // Verify if null data is not being passed
        if (sActivationToken == null) {
            return null;
        }
        Session oSession = null;
        Transaction oTransaction = null;
        try {
            sActivationToken = IServiceUtil.getTwoWayEncValue(sActivationToken,
                    sGlobalINumber);
            Principal oPrincipalByActivationToken = new Principal();
            Principal oPrincipalFromSyn = new Principal();
            try {
                // Get Global I-Number of the principal
                oSession = HibernateUtil.getSessionFactory().openSession();
                oTransaction = oSession.beginTransaction();
                oPrincipalByActivationToken = ISSOHelpers
                        .fetchPrincipalByActivationToken(sActivationToken,
                                oSession, oTransaction);
                oPrincipalByActivationToken.debug("getGlobalINumber(): ");
            } catch (IServiceException ise) {
                logger.warn("getGlobalINumber(): returning null, Exception :"
                        + ise.getMessage());
                return null;
            }
            Synonym oSyn = ISSOHelpers.fetchGINo(oPrincipalByActivationToken
                    .getId(), oSession, oTransaction);
            oPrincipalFromSyn = oSyn.getPrincipal();
            // Verify the principal and its state
            if ((oPrincipalByActivationToken.getState() == ISSOConstants.STATE_PENDING)
                    && (oPrincipalByActivationToken.getId().longValue() == oPrincipalFromSyn
                            .getId().longValue())) {
                oTransaction.commit();
                logger.info("getGlobalINumber(): Exiting after commit");
                return oSyn.getSynonym();
            } else {
                oTransaction.rollback();
                logger.info("getGlobalINumber(): Exiting after rollback");
                return null;
            }
        } finally {
            if (oSession != null) {
                oSession.close();
            }
        }
    }

    /**
     * Logs the user in the system by verifying password, session and machine
     * cookie. If password is provided as null, session state is checked. If
     * state of session is active login is done otherwise an invalid session
     * exception is thrown
     * 
     * @param sGlobalInumber
     *            Global I-Number of the user to be logged in
     * @param sPassword
     *            Password of the user
     * @param sIBrokerName
     *            IBroker through which login request has been received
     * @param sSessionToken
     *            Session token of the machine from which user has attempted
     *            login
     * @param sMachineCookie
     *            Machine token of the machine from which user has attempted
     *            login
     * @throws IServiceException
     *             Thrown when either of GlobalInumber, IBrokerName,
     *             SessionToken, MachineCookie are null. Also, if principal does
     *             not belong to the same IBroker
     */
    public static void login(String sGlobalInumber, String sPassword,
            String sIBrokerName, String sSessionToken, String sMachineCookie,
            boolean bRememberMachine) throws IServiceException {
        logger.info("login() entry with data : GIN=" + sGlobalInumber
                + ",Password=" + sPassword + ", BrokerName=" + sIBrokerName
                + ", SessionToken=" + sSessionToken + ", MachineCookie="
                + sMachineCookie);
        // Check if required data has not been passed as null
        if (sGlobalInumber == null || sIBrokerName == null
                || sSessionToken == null || sMachineCookie == null) {
            throw new IServiceException(logger, 2028);
        }

        Session oSession = HibernateUtil.getSessionFactory().openSession();
        Transaction oTransaction = oSession.beginTransaction();

        // Get Principal Data Object
        Principal oPrincipal = (Principal) ISSOHelpers.fetchPrincipal(
                sGlobalInumber, oSession, oTransaction);
        oPrincipal.debug("LOGIN: ");

        // Verify if principal belongs to same IBroker
        if (oPrincipal.getBroker().getId().intValue() != getIBrokerId(
                sIBrokerName, oSession, oTransaction)) {
            oTransaction.rollback();
            throw new IServiceException(logger, 2016);
        }
        // verify Principal State
        if (oPrincipal.getState() != ISSOConstants.STATE_ACTIVE) {
            oTransaction.rollback();
            throw new IServiceException(logger, 2007);
        }
        // Verify Password/Session
        if (sPassword != null) {
            sPassword = IServiceUtil.getOneWayEncValue(sPassword);
            // Get Princpal's Meta DAta Object
            oSession.save(oPrincipal);
            PrincipalMetaData oPMData = getPrincipalMetaData(
                    oPrincipal.getId(), oSession, oTransaction);
            oSession.save(oPMData);
            oPMData.debug("LOGIN: ");
            if (!sPassword.equals(oPMData.getEncPasswd())) {
                oTransaction.rollback();
                throw new IServiceException(logger, 1001);
            }
        } else if (!verifySessionState(sGlobalInumber, sSessionToken, true,
                oSession, oTransaction)) {
            oTransaction.rollback();
            throw new IServiceException(logger, 2009);
        }

        try {
            // Encrypt cookies received
            sSessionToken = IServiceUtil.getOneWayEncValue(sSessionToken);
            sMachineCookie = IServiceUtil.getOneWayEncValue(sMachineCookie);
            // Create/Update session
            try {
                createUpdateSession(oPrincipal.getId(), sSessionToken,
                        oSession, oTransaction);
            } catch (Exception e) {
                logger.warn("login() : Create/Update session : exception="
                        + e.getMessage());
            }
            // Create/Update Machine cookie
            try {
                createUpdateMachineCookie(oPrincipal.getId(), sMachineCookie,
                        bRememberMachine, oSession, oTransaction);
            } catch (Exception e) {
                logger
                        .warn("login() : Create/Update Machine cookie : exception="
                                + e.getMessage());
            }
            oTransaction.commit();
            logger.info("login() : exit");
        } catch (Exception e) {
            logger.warn("login() : Exception :" + e.getMessage());
        } finally {
            if (oSession != null) {
                oSession.close();
            }
        }
    }

    /**
     * This method is used to get the information of a Principal, the data about
     * the principal is stored as the principal metadata
     * 
     * @param id
     * @param oSession
     *            Hibernate Session
     * @param oTransaction
     *            Hibernate Transaction for current session
     * @return metadata of given principal
     */
    private static PrincipalMetaData getPrincipalMetaData(Long id,
            Session oSession, Transaction oTransaction) {
        logger.info("getPrincipalMetaData() : entry with data : id=" + id);
        PrincipalMetaData oData = new PrincipalMetaData();
        Principal oPrincipal = (Principal) ISSOHelpers.fetch(Principal.class,
                id, oSession, oTransaction);
        oPrincipal.debug("GETPRINCIPALMETADATA");
        Iterator it = oPrincipal.getPrincipalMetaData().iterator();
        oData = (PrincipalMetaData) it.next();
        logger.info("getPrincipalMetaData() : exit, return PrincipalMetaData="
                + oData);
        return oData;
    }

    /**
     * Returns IBrokerID corresponding to IBroker Name
     * 
     * @param sIBrokerName
     *            Name of IBroker for which request has been recieved
     * @return ID of the IBroker
     * @throws IServiceException
     *             Thrown when IBroker name does not exist
     */
    private static int getIBrokerId(String sIBrokerName, Session oSession,
            Transaction oTransaction) throws IServiceException {
        logger.info("getIBrokerId() : entry with data : Brokername="
                + sIBrokerName);
        // Get IBroker ID using Ibroker Name
        IBroker oIBroker = (IBroker) ISSOHelpers.fetchIBroker(sIBrokerName,
                oSession, oTransaction);
        // Throw exception if Ibroker state not active
        oIBroker.debug("GETIBROKER");
        if (oIBroker.getState() == ISSOConstants.STATE_ACTIVE) {
            return oIBroker.getId().intValue();
        } else {
            throw new IServiceException(logger, 2004);
        }
    }

    /**
     * Activates the principal. Updates the password and sets state to "Active"
     * 
     * @param sGlobalINumber
     *            Global I-Number of the principal to be activated
     * @param sFirstName
     *            First name of the principal
     * @param sLastName
     *            Last name of the principal
     * @param sGreeting
     *            Personalized greeting
     * @param sEmail
     *            Email address of the principal
     * @param sPassword
     *            Password to be set for principal
     * @param iChalllengeQuestionId
     *            Id of challenge question
     * @param sRecoveryAnswer
     *            Recovery answer, can be used to fetch password later
     * @throws IServiceException
     *             Thrown when Global I-Number does not exist
     */
    public static void activateUpdatePrincipal(String sGlobalINumber,
            String sFirstName, String sLastName, String sGreeting,
            String sEmail, String sPassword, int iChalllengeQuestionId,
            String sRecoveryAnswer) throws IServiceException {
        logger.info("activateUpdatePrincipal(): entry with data : GIN="
                + sGlobalINumber + ",FirstName=" + sFirstName + ", LastName="
                + sLastName + ", Greeting=" + sGreeting + ", Email=" + sEmail
                + ", Password=" + sPassword + ", ChallengeQuestionID="
                + iChalllengeQuestionId);

        // Check if all the required values have been passed
        if (sGlobalINumber == null || sFirstName == null || sLastName == null
                || sGreeting == null || sEmail == null || sPassword == null
                || sRecoveryAnswer == null || iChalllengeQuestionId < 0) {
            throw new IServiceException(logger, 2028);
        }
        Session oSession = HibernateUtil.getSessionFactory().openSession();
        Transaction oTransaction = oSession.beginTransaction();
        // Check if principal has not been activated before
        try {
            Principal oPrincipal = ISSOHelpers.fetchPrincipal(sGlobalINumber,
                    oSession, oTransaction);
            if (oPrincipal.getState() != ISSOConstants.STATE_PENDING) {
                oTransaction.rollback();
                throw new IServiceException(logger, 2037);
            }
            // Encrypt data
            sPassword = IServiceUtil.getOneWayEncValue(sPassword);
            sGreeting = IServiceUtil.getTwoWayEncValue(sGreeting,
                    sGlobalINumber);
            sRecoveryAnswer = IServiceUtil.getOneWayEncValue(sRecoveryAnswer
                    .toLowerCase());
            oSession.save(oPrincipal);
            // Create Update vector
            PrincipalMetaData oData = (PrincipalMetaData) ISSOHelpers
                    .fetchMetaData(oPrincipal, oSession, oTransaction);
            oPrincipal.setState(ISSOConstants.STATE_ACTIVE);
            oData.setFirstName(sFirstName);
            oData.setLastName(sLastName);
            oData.setEncPasswd(sPassword);
            oData.setEmail(sEmail);
            oData.setEncGreeting(sGreeting);
            oData.setChallengeQuestionId(iChalllengeQuestionId);
            oData.setEncPwdRecAnswer(sRecoveryAnswer);
            // Activate Principal
            oData.update();
            oPrincipal.update();
            oTransaction.commit();
            logger.info("activateUpdatePrincipal(): exit after commit");
        } finally {
            if (oSession != null) {
                oSession.close();
            }
        }
    }

    /**
     * Verifies if the cookie AND Principal state are still valid. Also checks
     * if the session belongs to the same principal
     * 
     * @param sGlobalINumber
     *            Global I-Number for which login request has been received
     * @param sCookie
     *            Session of which validity is to be checked
     * @param bIsSessionCookie
     *            true: if Sessiosn cookie is to be verified <BR>
     *            false: if machine cookie is to be verified
     * @param oTransaction
     *            Hibernate Transaction
     * @param oSession
     *            Hibernate Session
     * @return true: If Cookie state = active <BR>
     *         false: If cookie state is NOT active
     * @throws IServiceException
     *             Thrown when either the principal or cookie to be verified
     *             does not exist or has been passed as null
     */
    public static boolean verifySessionState(String sGlobalINumber,
            String sCookie, boolean bIsSessionCookie, Session oSession,
            Transaction oTransaction) throws IServiceException {
        logger.info("verifySessionState(): entry with data : GIN="
                + sGlobalINumber + ",Cookie=" + sCookie);

        if (sGlobalINumber == null || sCookie == null) {
            throw new IServiceException(logger, 2028);
        }
        long expireTime;
        short iTypeFlag;
        boolean bFlag = false;
        // get session object for Session
        try {
            if (oSession == null) {
                oSession = HibernateUtil.getSessionFactory().openSession();
                bFlag = true;
            }
            if (oTransaction == null)
                oTransaction = oSession.beginTransaction();
            sCookie = IServiceUtil.getOneWayEncValue(sCookie);
            Cookie oSessionCookie = new Cookie();
            // check if session cookie exists
            if (bIsSessionCookie) {
                expireTime = ((long) ISSOConstants.VALIDITY_SESSION_SERVER * 1000);
                iTypeFlag = ISSOConstants.SESSION;
            } else {
                expireTime = ((long) ISSOConstants.VALIDITY_MACHINE_SERVER * 1000);
                iTypeFlag = ISSOConstants.MACHINE;
            }
            oSessionCookie = ISSOHelpers.fetchCookieByName(sCookie, iTypeFlag,
                    oSession, oTransaction);
            oSessionCookie.debug("IN VERIFYSESSIONSTATE 1");
            // Get principal object
            Principal oPrincipal = new Principal();
            oPrincipal = ISSOHelpers.fetchPrincipal(sGlobalINumber, oSession,
                    oTransaction);
            oPrincipal.debug("IN VERIFYSESSIONSTATE 2");
            // Check if the session cookie belongs to same principal
            if (oPrincipal.getId().longValue() != oSessionCookie.getPrincipal()
                    .getId().longValue()) {
                if (bFlag)
                    oTransaction.rollback();
                throw new IServiceException(logger, 2035);
            }
            // Verify principal state
            if (oPrincipal.getState() != ISSOConstants.STATE_ACTIVE) {
                if (bFlag)
                    oTransaction.rollback();
                throw new IServiceException(logger, 2007);
            }
            // Verify session state
            if (oSessionCookie.getState() != ISSOConstants.STATE_ACTIVE) {
                if (bFlag)
                    oTransaction.rollback();
                throw new IServiceException(logger, 2009);
            }
            long lDate = new Date().getTime();
            logger.info("verifySessionState(): exit");
            // Return state of Machine Cookie
            return ((oSessionCookie.getState() == ISSOConstants.STATE_ACTIVE && oSessionCookie
                    .getModificationTime().getTime()
                    + expireTime > lDate) ? true : false);
        } finally {
            if (bFlag) {
                oSession.close();
                oTransaction = null;
                oSession = null;
            }
        }
    }

    /**
     * Creates session if sSessionToken does not exist, otherwise updates the
     * 
     * @param iPrincipalId
     *            Principal of the Global I-Number/Synonym
     * @param sEncSessionToken
     *            Session Token used to identifiy session
     * @param oSession
     *            Hibernate Session
     * @param oTransaction
     *            Hibernate Transaction
     * @throws IServiceException
     */
    private static void createUpdateSession(Long iPrincipalId,
            String sEncSessionToken, Session oSession, Transaction oTransaction)
            throws IServiceException {
        logger.info("createUpdateSession(): entry with data : PrincipalId="
                + iPrincipalId + ", SessionToken=" + sEncSessionToken);

        boolean bIsSessionExist = false;
        // Verify if session exists
        try {
            bIsSessionExist = isSessionActive(sEncSessionToken, oSession,
                    oTransaction);
        } catch (IServiceException ise) {
            logger
                    .warn("createUpdateSession() : Exception : session does not exist, set bIsSessionExist = false");
            bIsSessionExist = false;
        }
        if (!bIsSessionExist) {
            // Create Session
            Cookie oCookie = new Cookie();
            oCookie.setEncCookieName(sEncSessionToken);
            oCookie.setState((short) ISSOConstants.STATE_ACTIVE);
            oCookie.setTypeFlag((short) ISSOConstants.SESSION);
            Principal pp = (Principal) ISSOHelpers.fetch(Principal.class,
                    iPrincipalId, oSession, oTransaction);
            pp.debug("IN CREATEUPDATESESSION 1");
            oCookie.setPrincipal((Principal) ISSOHelpers.fetch(Principal.class,
                    iPrincipalId, oSession, oTransaction));
            oCookie.debug("IN CREATEUPDATESESSION 2");
            oCookie.insert();
            oSession.save(oCookie);
            logger.info("createUpdateSession(): exit after cookie save");
        } else {
            // update cookie
            Cookie oCookie = ISSOHelpers.fetchCookieByName(sEncSessionToken,
                    ISSOConstants.SESSION, oSession, oTransaction);
            oCookie.update(true);
            oSession.save(oCookie);
            logger.info("createUpdateSession(): exit after cookie update");
            return;
        }
    }

    /**
     * Updates cookie if already exists and is to be remembered. <BR>
     * Deletes cookie if exists and doesnt need to be remembered. <BR>
     * Creates cookie if doesnt exist but has to be rememebered
     * 
     * @param iPrincipalId
     *            ID of the principal for which machine cookie is to be set
     * @param sEncMachineCookie
     *            Machine cookie to be created/updated
     * @param bRememberMachine
     *            true: if machine cookie is to be created <BR>
     *            false: if machine is NOT to be created
     * @param oSession
     *            Hibernate Session
     * @param oTransaction
     *            Hibernate Transaction
     * @throws IServiceException
     *             Thrown if Machine cookie could not be created/updated due to
     *             hash collision
     */
    private static void createUpdateMachineCookie(Long iPrincipalId,
            String sEncMachineCookie, boolean bRememberMachine,
            Session oSession, Transaction oTransaction)
            throws IServiceException {
        logger
                .info("createUpdateMachineCookie(): entry with data : PrincipalId: "
                        + iPrincipalId
                        + ", EncMachineCookie: "
                        + sEncMachineCookie);
        Cookie oMachineCookie = new Cookie();
        oMachineCookie.setEncCookieName(sEncMachineCookie);
        oMachineCookie.setTypeFlag(ISSOConstants.MACHINE);
        boolean mcvalid = true;
        try {
            oMachineCookie = (Cookie) ISSOHelpers.fetchCookieByName(
                    sEncMachineCookie, ISSOConstants.MACHINE, oSession,
                    oTransaction);
        } catch (IServiceException e) {
            logger.warn("no cllokie found for token: " + sEncMachineCookie);
            mcvalid = false;
        }

        if (bRememberMachine) {
            oMachineCookie.setState(ISSOConstants.STATE_ACTIVE);
            if (mcvalid) {
                // retrieve & update the cookie
                oMachineCookie.update(true);
                oMachineCookie.debug("IN CREATEUPDATEMACHINECOOKIE 1");
            } else {
                // create a new cookie
                oMachineCookie.setPrincipal((Principal) ISSOHelpers.fetch(
                        Principal.class, iPrincipalId, oSession, oTransaction));
                oMachineCookie.insert();
                oSession.save(oMachineCookie);
                oMachineCookie.debug("IN CREATEUPDATEMACHINECOOKIE 0");
            }
        } else if (mcvalid) {
            // retrieve & delete cookie
            oMachineCookie.remove();
            oSession.delete(oMachineCookie);
            oMachineCookie.debug("IN CREATEUPDATEMACHINECOOKIE 3");
        }
    }

    /**
     * Verifies if the session is active or not
     * 
     * @param sEncSessionToken
     *            Session token to be validated
     * @param oSession
     *            Hibernate Session
     * @param oTransaction
     *            Hibernate Transaction
     * @return true: If session state is active <BR>
     *         false: If the session state is NOT active
     * @throws IServiceException
     *             Thrown if sEncSessionToken does not exist
     */
    private static boolean isSessionActive(String sEncSessionToken,
            Session oSession, Transaction oTransaction)
            throws IServiceException {
        logger.info("isSessionActive(): entry with data : EncSessionToken="
                + sEncSessionToken);
        // Get session object
        Cookie oSessionCookie = new Cookie();
        oSessionCookie = ISSOHelpers.fetchCookieByName(sEncSessionToken,
                ISSOConstants.SESSION, oSession, oTransaction);
        oSessionCookie.debug("IN ISSESSIONACTIVE");
        // Return Session state
        long expireTime = ISSOConstants.VALIDITY_SESSION_SERVER * 1000;
        long lDate = new Date().getTime();
        // Return state of Machine Cookie
        logger.info("isSessionActive(): exit");
        return ((oSessionCookie.getState() == ISSOConstants.STATE_ACTIVE && oSessionCookie
                .getModificationTime().getTime()
                + expireTime > lDate) ? true : false);
    }

    /**
     * Updates Principal's Security data after valiadating if the session is
     * still active
     * 
     * @param sGlobalINumber
     *            Global I-Number of the user
     * @param sSessionToken
     *            Session token from the session cookie
     * @param sGreeting
     *            Personalised greeting in clear text
     * @param iChallengeQuestionId
     *            ID of the Challenge question
     * @param sPwdRecoveryAnswer
     *            Answer to challenge question
     * @throws IServiceException
     *             Thrown if Principal or session does not exist or if updation
     *             could not be performed
     */
    public static void updatePrincipalSecurityInfo(String sGlobalINumber,
            String sSessionToken, String sGreeting, int iChallengeQuestionId,
            String sPwdRecoveryAnswer) throws IServiceException {
        logger.info("updatePrincipalSecurityInfo(): entry with data : GIN="
                + sGlobalINumber + ", SessionToken=" + sSessionToken
                + ", Greeting=" + sGreeting + ", ChallengeQuestionId="
                + iChallengeQuestionId + ", PasswordRecoveryAnswer="
                + sPwdRecoveryAnswer);
        Session oSession = HibernateUtil.getSessionFactory().openSession();
        Transaction oTransaction = oSession.beginTransaction();
        try {
            // Verify Principal and Session state
            if (!verifySessionState(sGlobalINumber, sSessionToken, true,
                    oSession, oTransaction)) {
                return;
            }
            // Get Principal Data Object
            Principal oPrincipal = null;
            oPrincipal = (Principal) ISSOHelpers.fetchPrincipal(sGlobalINumber,
                    oSession, oTransaction);
            if (oPrincipal == null) {
                oTransaction.rollback();
                throw new IServiceSystemException(logger, 2006);
            }
            // Create principal object to be updated
            PrincipalMetaData oPMData = getPrincipalMetaData(
                    oPrincipal.getId(), oSession, oTransaction);
            // Update greeting if not null
            if (sGreeting != null) {
                oPMData.setEncGreeting(IServiceUtil.getTwoWayEncValue(
                        sGreeting, sGlobalINumber));
            }
            // Update Challenge question id if not -1
            if (iChallengeQuestionId > 0) {
                oPMData.setChallengeQuestionId(iChallengeQuestionId);
            }
            // Update Pwd recovery answer if not null
            if (sPwdRecoveryAnswer != null) {
                oPMData.setEncPwdRecAnswer(IServiceUtil
                        .getOneWayEncValue(sPwdRecoveryAnswer));
            }
            // Update Principal
            oSession.save(oPrincipal);
            oSession.save(oPMData);
            oPMData.update();
            sSessionToken = IServiceUtil.getOneWayEncValue(sSessionToken);
            updateSessionCookie(sSessionToken, oSession, oTransaction);
            oTransaction.commit();
            logger.info("updatePrincipalSecurityInfo(): exit after commit");
        } finally {
            if (oSession != null) {
                oSession.close();
            }
        }
    }

    /**
     * Updates Principal's Profile data after valiadating if the session is
     * still active
     * 
     * @param sGlobalINumber
     *            Global I-Number of the user
     * @param sSessionToken
     *            Session token from the session cookie
     * @param sFirstName
     *            First name of principal
     * @param sLastName
     *            Last name of principal
     * @param sEmailAddress
     *            Email address of principal
     * @throws IServiceException
     *             Thrown if either the principal or session token does not
     *             exist
     */
    public static void updatePrincipalProfile(String sGlobalINumber,
            String sSessionToken, String sFirstName, String sLastName,
            String sEmailAddress) throws IServiceException {
        logger.info("updatePrincipalProfile() : entry with data : GIN="
                + sGlobalINumber + ", SessionToken=" + sSessionToken
                + ",FirstName=" + sFirstName + ", LastName=" + sLastName
                + ", Email=" + sEmailAddress);

        Session oSession = HibernateUtil.getSessionFactory().openSession();
        Transaction oTransaction = oSession.beginTransaction();
        // verify if Principal and session state are valid
        try {
            if (!verifySessionState(sGlobalINumber, sSessionToken, true,
                    oSession, oTransaction)) {
                return;
            }
            Principal oPrincipal = null;
            oPrincipal = (Principal) ISSOHelpers.fetchPrincipal(sGlobalINumber,
                    oSession, oTransaction);
            // Create principal object to be updated
            PrincipalMetaData oPMData = getPrincipalMetaData(
                    oPrincipal.getId(), oSession, oTransaction);
            // Update Firstname if not null
            if (sFirstName != null) {
                oPMData.setFirstName(sFirstName);
            }
            // Update secondname if not null
            if (sLastName != null) {
                oPMData.setLastName(sLastName);
            }
            // Update Email Add if not null
            if (sEmailAddress != null) {
                oPMData.setEmail(sEmailAddress);
            }
            // Update Principal
            oSession.save(oPrincipal);
            oSession.save(oPMData);
            oPMData.update();
            sSessionToken = IServiceUtil.getOneWayEncValue(sSessionToken);
            updateSessionCookie(sSessionToken, oSession, oTransaction);
            oTransaction.commit();
            logger.info("updatePrincipalProfile() : exit after commit");
        } finally {
            if (oSession != null) {
                oSession.close();
            }
        }
    }

    /**
     * Updates password, if the session is valid and old password matches the
     * existing password. Password can also be updated by providing SessionToken
     * and OldPassword as null. This special case is required when principal is
     * to be activated.
     * 
     * @param sGlobalINumber
     *            Global I-Number of the user
     * @param sSessionToken
     *            Session token
     * @param sOldPassword
     *            Old Password provided by the user
     * @param sNewPassword
     *            Password to be changed to
     * @throws IServiceException
     */
    public static void updatePassword(String sGlobalINumber,
            String sSessionToken, String sOldPassword, String sNewPassword)
            throws IServiceException {
        logger.info("updatePassword(): entry with data : GIN=" + sGlobalINumber
                + ", SessionToken=" + sSessionToken + ",OldPassword="
                + sOldPassword + ", NewPassword=" + sNewPassword);
        // Check if null has not been provided
        if (sGlobalINumber == null || sNewPassword == null) {
            throw new IServiceException(logger, 2028);
        }
        Session oSession = HibernateUtil.getSessionFactory().openSession();
        Transaction oTransaction = oSession.beginTransaction();
        try {
            Principal oPrincipal = null;
            oPrincipal = (Principal) ISSOHelpers.fetchPrincipal(sGlobalINumber,
                    oSession, oTransaction);
            oPrincipal.debug("IN UPDATE PWD");
            // verify PRincipal State
            if (oPrincipal.getState() != ISSOConstants.STATE_ACTIVE) {
                oTransaction.rollback();
                throw new IServiceException(logger, 2007);
            }
            // Create principal object to be updated
            PrincipalMetaData oPMData = getPrincipalMetaData(
                    oPrincipal.getId(), oSession, oTransaction);
            oPMData.debug("IN UPDATE PWD");
            /*
             * Verify Session and password only when sEncOldPassword AND
             * sSessionToken are null
             */
            if (sOldPassword != null && sSessionToken != null) {
                // Encrypt Session token and Password
                sOldPassword = IServiceUtil.getOneWayEncValue(sOldPassword);
                if (verifySessionState(sGlobalINumber, sSessionToken, true,
                        oSession, oTransaction)) {
                    // Get Principal object to verify old password provided
                    // Verify Password
                    if (!oPMData.getEncPasswd().equals(sOldPassword)) {
                        oTransaction.rollback();
                        throw new IServiceException(logger, 1001);
                    }
                } else {
                    oTransaction.rollback();
                    return;
                }
            }// Old Pwd and Session NOT NUll
            // Create Principal object to update password
            oPMData.setEncPasswd(IServiceUtil.getOneWayEncValue(sNewPassword));
            oSession.save(oPrincipal);
            oSession.save(oPMData);
            oPMData.update();
            oTransaction.commit();
            logger.info("updatePassword(): exit after commit");
        } finally {
            if (oSession != null) {
                oSession.close();
            }
        }
    }

    /**
     * Gets the security data of the principal if the session is valid
     * 
     * @param sGlobalINumber
     *            Global I-Number of the user
     * @param sSessionToken
     *            Sessiosn token
     * @return Principal object with security data
     * @throws IServiceException
     *             Thrown either when Global I-Number or Session token does not
     *             exist
     */
    public static Principal getPrincipalSecurityInfo(String sGlobalINumber,
            String sSessionToken) throws IServiceException {
        logger.info("getPrincipalSecurityInfo(): entry with GIN="
                + sGlobalINumber + ", SessionID=" + sSessionToken);
        // Check if Global I-Number has not been passed as null
        if (sGlobalINumber == null) {
            throw new IServiceException(logger, 2028);
        }
        Session oSession = HibernateUtil.getSessionFactory().openSession();
        Transaction oTransaction = oSession.beginTransaction();
        try {
            if (sSessionToken != null) {
                /*
                 * Verify principal and session state and check if session
                 * belongs to same principal
                 */
                if (!verifySessionState(sGlobalINumber, sSessionToken, true,
                        oSession, oTransaction)) {
                    return null;
                }
            } else {
                // Verify principal state
                if (!isPrincipalStateActive(sGlobalINumber, oSession,
                        oTransaction)) {
                    oTransaction.rollback();
                    throw new IServiceException(logger, 2007);
                }
            }
            // Create Principal object
            Principal oPrincipal = null;
            oPrincipal = (Principal) ISSOHelpers.fetchPrincipal(sGlobalINumber,
                    oSession, oTransaction);
            oSession.save(oPrincipal);
            // Create principal object to be updated
            PrincipalMetaData oPMData = getPrincipalMetaData(
                    oPrincipal.getId(), oSession, oTransaction);
            oSession.save(oPrincipal);
            oSession.save(oPMData);
            // Get Principal object
            String sEncGreeting = oPMData.getEncGreeting();
            oPrincipal.setUnEncryptedGreeting(IServiceUtil.getTwoWayDecValue(
                    sEncGreeting, sGlobalINumber));
            oSession.save(oPrincipal);
            oSession.save(oPMData);
            oSession.update(oPrincipal);
            oSession.update(oPMData);
            oTransaction.commit();
            logger.info("getPrincipalSecurityInfo(): exit, return Principal="
                    + oPrincipal);
            return oPrincipal;
        } finally {
            if (oSession != null) {
                oSession.close();
            }
        }
    }

    /**
     * Gets the principal's profile data if the session is valid
     * 
     * @param sGlobalINumber
     *            Global I-Number of the user
     * @param sSessionToken
     *            Session token
     * @return Princiapl object with security data
     * @throws IServiceException
     *             Thrown either when Global I-Number or Session token does not
     *             exist
     */
    public static Principal getPrincipalProfile(String sGlobalINumber,
            String sSessionToken) throws IServiceException {
        logger.info("getPrincipalProfile(): entry with GIN=" + sGlobalINumber
                + ", sessionID=" + sSessionToken);
        // Check if Global I-Number has not been passed as null
        if (sGlobalINumber == null) {
            throw new IServiceException(logger, 2028);
        }
        Session oSession = HibernateUtil.getSessionFactory().openSession();
        Transaction oTransaction = oSession.beginTransaction();
        // Check if only personliased greeting is to be provided
        try {
            if (sSessionToken != null) {
                /*
                 * Verify principal and session state and check if session
                 * belongs to same principal
                 */
                if (!verifySessionState(sGlobalINumber, sSessionToken, true,
                        oSession, oTransaction)) {
                    return null;
                }
            } else {
                // Verify principal state
                if (!isPrincipalStateActive(sGlobalINumber, oSession,
                        oTransaction)) {
                    oTransaction.rollback();
                    throw new IServiceException(logger, 2007);
                }
            }
            // Create Principal object
            Principal oPrincipal = null;
            oPrincipal = (Principal) ISSOHelpers.fetchPrincipal(sGlobalINumber,
                    oSession, oTransaction);
            oTransaction.commit();
            logger
                    .info("getPrincipalProfile(): exit after commit, return Principal="
                            + oPrincipal);
            return oPrincipal;
        } finally {
            if (oSession != null) {
                oSession.close();
            }
        }
    }

    /**
     * Updates the session cookie, it updates the modification time of the
     * cookie and hence expiry time also extends
     * 
     * @param sSessionToken
     *            Current Session id
     * @param oSession
     *            Hibernate Session
     * @param oTransaction
     *            Hibernate Transaction
     * @throws IServiceException
     */
    private static void updateSessionCookie(String sSessionToken,
            Session oSession, Transaction oTransaction)
            throws IServiceException {
        logger.info("updateSessionCookie(): entry");
        Cookie oCookie = ISSOHelpers.fetchCookieByName(sSessionToken,
                ISSOConstants.SESSION, oSession, oTransaction);
        oCookie.update(true);
        logger.info("updateSessionCookie(): exit after update");
    }

    /**
     * Logs out user and makes the current session INACTIVE
     * 
     * @param sSessionToken
     *            Session token for which session is be invalidated
     * @throws IServiceException
     *             Throws if Session token does not exists
     */
    public static void logout(String sSessionToken) throws IServiceException {
        logger.info("logout() entry with SID=" + sSessionToken);
        // Check if null data has not been provided
        if (sSessionToken == null) {
            throw new IServiceException(logger, 2028);
        }
        Session oSession = HibernateUtil.getSessionFactory().openSession();
        Transaction oTransaction = oSession.beginTransaction();
        // Makes user session as inactive
        try {
            sSessionToken = IServiceUtil.getOneWayEncValue(sSessionToken);
            ISSOHelpers.deleteSession(sSessionToken, oSession, oTransaction);
            oTransaction.commit();
            logger.info("logout(): successfully done");
        } finally {
            oSession.close();
        }
    }

    /**
     * Saves the SAML Response for the current login session
     * 
     * @param sSessionToken
     *            Session for which login has been done
     * @param sResponse
     *            Response to be sent
     * @throws IServiceException
     *             Thrown when response could not be saved or when either
     *             sArtifactId or sResponse is null
     */
    public static void saveSAMLResponse(String sArtifactId,
            String sSessionToken, String sResponse) throws IServiceException {
        logger.info("saveSAMLResponse(): entry with data : ArtifactId="
                + sArtifactId + ", SessionId=" + sSessionToken + ", Response="
                + sResponse);
        // Check if null data is not being passed
        if (sArtifactId == null || sResponse == null) {
            throw new IServiceException(logger, 2028);
        }
        Session oSession = HibernateUtil.getSessionFactory().openSession();
        Transaction oTransaction = oSession.beginTransaction();
        // Encrypt Data
        sArtifactId = IServiceUtil.getOneWayEncValue(sArtifactId);
        try {
            Response oResponse = new Response();
            // Check if Session is valid
            if (sSessionToken != null) {
                sSessionToken = IServiceUtil.getOneWayEncValue(sSessionToken);
                Cookie oCookie = (Cookie) ISSOHelpers.fetchCookieByName(
                        sSessionToken, ISSOConstants.SESSION, oSession,
                        oTransaction);
                oSession.save(oCookie);
                oResponse.setCookie(oCookie);
            }
            oResponse.setEncArtifactId(sArtifactId);
            oResponse.setResponse(sResponse);
            oResponse.setState(ISSOConstants.STATE_ACTIVE);
            try {
                oResponse.insert();
                oSession.save(oResponse);
            } catch (IServiceException ise) {
                oTransaction.rollback();
                if (ise.getErrorCode() == 101)
                    throw new IServiceSystemException(logger, 2011);
            }
            oTransaction.commit();
            logger.info("saveSAMLResponse(): exit after commit");
        } finally {
            if (oSession != null) {
                oSession.close();
            }
        }
    }

    /**
     * Retrieves the response for artifact id provided and sets the state of
     * response to Inactive.
     * 
     * @param sArtifactId
     *            Artifact ID for response is to be retreived
     * @return Response corresponding to Artifact Id
     * @throws IServiceException
     *             Thrown if artifact Id does not exist or a null has been
     *             passed
     */
    public static String getSAMLResponse(String sArtifactId)
            throws IServiceException {
        logger.debug("getSAMLResponse(): entry with artifact=" + sArtifactId);
        // Check if null data is not being passed
        if (sArtifactId == null) {
            throw new IServiceException(logger, 2028);
        }
        sArtifactId = IServiceUtil.getOneWayEncValue(sArtifactId);
        Session oSession = HibernateUtil.getSessionFactory().openSession();
        Transaction oTransaction = oSession.beginTransaction();
        try {
            Response oResponse = ISSOHelpers.fetchResponse(sArtifactId,
                    oSession, oTransaction);
            oSession.save(oResponse);
            String response = oResponse.getResponse();
            oTransaction.commit();
            oResponse.remove();
            logger.info("getSAMLResponse(): exit, return response=" + response);
            return response;
        } finally {
            oSession.close();
        }
    }

    /**
     * Verifies if the synonym belongs to the princpal and the associated
     * principal state is active.
     * 
     * @param sGlobalINumber
     *            Global I-Number of the synonym
     * @param sSynonym
     *            Synonym to be verified
     * @return true: If the syninym is subscrtibed to the service <BR>
     *         false: If the sybnonym is not subscribed to the service
     * @throws IServiceException
     *             Thrown if the Global I-Number does not exist
     */
    public static boolean verifySynonym(String sGlobalINumber, String sSynonym,
            String sIBroker) throws IServiceException {
        logger.info("verifySynonym(): entry with GIN=" + sGlobalINumber
                + ", SYN=" + sSynonym + ", IBroker=" + sIBroker);
        // Check if null data is not being passed
        if (sGlobalINumber == null || sSynonym == null) {
            throw new IServiceException(logger, 2028);
        }
        Session oSession = HibernateUtil.getSessionFactory().openSession();
        Transaction oTransaction = oSession.beginTransaction();
        try {
            Principal oPrincipal = ISSOHelpers.fetchPrincipal(sGlobalINumber,
                    oSession, oTransaction);
            // Check if principal state is active or not
            if (getIBrokerId(sIBroker, oSession, oTransaction) == oPrincipal
                    .getBroker().getId().intValue()) {
                if (isPrincipalStateActive(sGlobalINumber, oSession,
                        oTransaction)) {
                    Set oSynonyms = ISSOHelpers.fetchAllSynonyms(
                            sGlobalINumber, oSession, oTransaction);
                    for (Iterator oIter = oSynonyms.iterator(); oIter.hasNext();) {
                        Synonym oSynonym = (Synonym) oIter.next();
                        if (oSynonym.getSynonym().equals(sSynonym)) {
                            oTransaction.commit();
                            logger.info("verifySynonym(): exit, return true");
                            return true;
                        }
                    }
                } else {
                    throw new IServiceException(logger, 2007);
                }
            }
        } catch (IServiceException ise) {
            logger.warn("verifySynonym(): IService Exception, Code : "
                    + ise.getErrorCode() + ", Message :" + ise.getMessage());
            oTransaction.rollback();
            if (!(ise.getErrorCode() == 2004))
                throw ise;
        } finally {
            oSession.close();
        }
        logger.warn("verifySynonym(): returning false for GIN="
                + sGlobalINumber + ", SYN=" + sSynonym + ", IBroker="
                + sIBroker);
        return false;
    }

    /**
     * Verifies if the Password recovery answer provided is correct
     * 
     * @param sChallengeAnswer
     *            Answer to Password recovery challenge question
     * @param sGlobalINumber
     *            Global I-Number of the I-Name for which password is to be
     *            recovered
     * @return true: If the answer provided matches <BR>
     *         false: If the password provided does not match
     * @throws IServiceException
     *             Thrown if null data has been passed. Or principal state is
     *             not active
     */
    public static boolean verifyChallengeAnswer(String sGlobalINumber,
            String sChallengeAnswer) throws IServiceException {
        logger.info("verifychallengeAnswer() entry with GIN=" + sGlobalINumber
                + ", chAns=" + sChallengeAnswer);
        // Verify if null has not been passed
        if (sGlobalINumber == null || sChallengeAnswer == null) {
            throw new IServiceException(logger, 2028);
        }
        Session oSession = HibernateUtil.getSessionFactory().openSession();
        Transaction oTransaction = oSession.beginTransaction();
        // Verify principal state
        try {
            if (!isPrincipalStateActive(sGlobalINumber, oSession, oTransaction)) {
                oTransaction.rollback();
                throw new IServiceException(logger, 2007);
            }
            // Encrypt Challenge answer
            sChallengeAnswer = sChallengeAnswer.toLowerCase();
            sChallengeAnswer = IServiceUtil.getOneWayEncValue(sChallengeAnswer);
            // Get Principal object to verify password recovery answer
            Principal oPrincipal = null;
            oPrincipal = (Principal) ISSOHelpers.fetchPrincipal(sGlobalINumber,
                    oSession, oTransaction);
            // Create principal object to be updated
            PrincipalMetaData oPMData = getPrincipalMetaData(
                    oPrincipal.getId(), oSession, oTransaction);
            // Validate Answer provided
            if (sChallengeAnswer.equalsIgnoreCase(oPMData.getEncPwdRecAnswer())) {
                oTransaction.commit();
                logger.info("verifyChallengeAnswer(): returning true");
                return true;
            } else {
                oTransaction.rollback();
                logger.warn("verifyChallengeAnswer(): returning false for GIN="
                        + sGlobalINumber + ", chAns=" + sChallengeAnswer);
                return false;
            }
        } finally {
            oSession.close();
        }
    }

    /**
     * Gets the state of the Principal and checks whether it is ACTIVE or not.
     * It returns true if state is ACTIVE, false otherwise
     * 
     * @param sGlobalINumber
     *            Global I-Number whoose state is to be checked
     * @param oTransaction
     *            Hibernte Transaction
     * @param oSession
     *            Hibernate Session
     * @return true: If principal state is active <BR>
     *         false: If the principal state is not active
     * @throws IServiceException
     *             Thrown if sGlobalINumber does not exist
     */
    private static boolean isPrincipalStateActive(String sGlobalINumber,
            Session oSession, Transaction oTransaction)
            throws IServiceException {
        // Get Principal object to be verified
        Principal oPrincipal = null;
        oPrincipal = ISSOHelpers.fetchPrincipal(sGlobalINumber, oSession,
                oTransaction);
        // Return principal state
        return ((oPrincipal.getState() == ISSOConstants.STATE_ACTIVE)
                ? true
                : false);
    }

    /**
     * Returns reputation score for Global I-Number using Contact Requests Sent
     * and Complaints Recieved
     * 
     * @param sGlobalINumber
     *            Global I-Number of the user of which reputation score is to be
     *            calculated
     * @param sSessionToken
     *            Session in which the request is made
     * @return Reputation score OR -1 if reputation score could not be
     *         calculated
     * @throws IServiceException
     *             Thrown when the parameters passed are null
     */
    public static int getReputationScore(String sGlobalINumber,
            String sSessionToken) throws IServiceException {
        logger.info("getReputationScore(): entry with data : GIN="
                + sGlobalINumber + ", SessionId=" + sSessionToken);
        // Verify if null has not been passed
        if (sGlobalINumber == null || sSessionToken == null) {
            throw new IServiceException(logger, 2028);
        }
        Session oSession = HibernateUtil.getSessionFactory().openSession();
        Transaction oTransaction = oSession.beginTransaction();
        try {
            sSessionToken = IServiceUtil.getOneWayEncValue(sSessionToken);
            if (isPrincipalStateActive(sGlobalINumber, oSession, oTransaction)
                    && isSessionActive(sSessionToken, oSession, oTransaction)) {
                // create principal object to get its Total contacts and
                // complaints
                Principal oPrincipal = ISSOHelpers.fetchPrincipal(
                        sGlobalINumber, oSession, oTransaction);
                PrincipalMetaData oData = getPrincipalMetaData(oPrincipal
                        .getId(), oSession, oTransaction);
                // Calculate Reputation score
                int iReputationScore = (int) ((1 - (oData
                        .getContactCompReceived() / oData.getContactReqSent())) * 100);
                oTransaction.commit();
                logger
                        .info("getReputationScore(): exit, return ReputationScore="
                                + iReputationScore);
                return iReputationScore;
            }
        } catch (Exception e) {
            logger.warn("getReputationScore(): Exception :" + e.getMessage());
            oTransaction.rollback();
            return -1;
        } finally {
            oSession.close();
        }
        return -1;
    }

    /**
     * Increments the contact requests count by 1. Works only when session state
     * is active
     * 
     * @param sGlobalINumber
     *            Global I-Number of the user logged in
     * @param sSessionToken
     *            Current Session token
     * @throws IServiceException
     */
    public static void updateContactRequestScore(String sGlobalINumber,
            String sSessionToken) throws IServiceException {
        logger.info("updateContactRequestScore(): entry with data : GIN="
                + sGlobalINumber + ", SessionId=" + sSessionToken);
        Session oSession = HibernateUtil.getSessionFactory().openSession();
        Transaction oTransaction = oSession.beginTransaction();
        try {
            sSessionToken = IServiceUtil.getOneWayEncValue(sSessionToken);
            if (isPrincipalStateActive(sGlobalINumber, oSession, oTransaction)
                    && isSessionActive(sSessionToken, oSession, oTransaction)) {
                Principal oPrincipal = null;
                /*
                 * Principal object to get Request Sent Score
                 */
                oPrincipal = ISSOHelpers.fetchPrincipal(sGlobalINumber,
                        oSession, oTransaction);
                PrincipalMetaData oData = getPrincipalMetaData(oPrincipal
                        .getId(), oSession, oTransaction);
                oData.debug("IN UPDATE CONTACT REQ SCORE : ");
                int lRequestScrore = oData.getContactReqSent();
                /*
                 * Principal object to increment Request Sent Score
                 */
                lRequestScrore++; // Increment
                oData.setContactReqSent(lRequestScrore);
                oData.update();
                oPrincipal.update();
                oTransaction.commit();
                logger.info("updateContactRequestScore(): exit after commit");
            } else {
                oTransaction.rollback();
                logger.info("updateContactRequestScore(): exit after rollback");
                return;
            }
        } catch (Exception pe) {
            logger.warn("updateContactRequestScore() : Exception : "
                    + pe.getMessage());
        } finally {
            oSession.close();
        }
    }

    /**
     * Increments the complaint received requests count by 1. Works only when
     * session state is active
     * 
     * @param sGlobalINumber
     *            Global I-Number of the user logged in
     * @param sSessionToken
     *            Current Session token
     * @throws IServiceException
     * 
     */
    public static void updateComplaintScore(String sGlobalINumber,
            String sSessionToken) throws IServiceException {
        logger.info("updateComplaintScore(): entry with data : GIN="
                + sGlobalINumber + ", SessionId=" + sSessionToken);
        Session oSession = HibernateUtil.getSessionFactory().openSession();
        Transaction oTransaction = oSession.beginTransaction();
        try {
            sSessionToken = IServiceUtil.getOneWayEncValue(sSessionToken);
            if (isPrincipalStateActive(sGlobalINumber, oSession, oTransaction)
                    && isSessionActive(sSessionToken, oSession, oTransaction)) {
                Principal oPrincipal = null;
                /*
                 * Principal object to get Complaints received Score
                 */
                oPrincipal = ISSOHelpers.fetchPrincipal(sGlobalINumber,
                        oSession, oTransaction);
                oPrincipal.debug("IN UPDATE COMPLAINT SCORE: ");
                PrincipalMetaData oData = getPrincipalMetaData(oPrincipal
                        .getId(), oSession, oTransaction);
                oData.debug("IN UPDATE COMPLAINT SCORE : ");
                int lComplaintScrore = oData.getContactCompReceived();
                /*
                 * Principal object to increment Complaints received Score
                 */
                lComplaintScrore++; // Increment
                oData.setContactReqSent(lComplaintScrore);
                oData.update();
                oPrincipal.update();
                oTransaction.commit();
            } else {
                oTransaction.rollback();
                return;
            }
        } catch (IServiceException pe) {
            /*
             * Principal state is not active
             */
            logger
                    .warn("updateComplaintScore() : Principal state is not active, Exception : "
                            + pe.getMessage());
        } finally {
            oSession.close();
        }
    }

    /**
     * Gets the meta data information of the given Principal
     * 
     * @param oPrincipal
     *            Use to fetch its metadata
     * @return metadata of given Principal
     */
    public static PrincipalMetaData getMetaData(Principal oPrincipal) {
        logger.info("getMetaData(): entry");
        Session oSession = HibernateUtil.getSessionFactory().openSession();
        Transaction oTransaction = oSession.beginTransaction();
        try {
            PrincipalMetaData oData = ISSOHelpers.fetchMetaData(oPrincipal,
                    oSession, oTransaction);
            oTransaction.commit();
            logger.info("getMetaData(): exit, return PrincipalMetadata="
                    + oData);
            return oData;
        } finally {
            oSession.close();
        }
    }

    /**
     * Gets Global I-Number of the given synonym
     * 
     * @param sSynonym
     *            Name of the synonym
     * @return Global I-Number
     * @throws IServiceException
     */
    public static String getGlobalINumberBySynonym(String sSynonym)
            throws IServiceException {
        logger.info("getGlobalINumberBySynonym() : entry with data : Synonym="
                + sSynonym);
        Session oSession = HibernateUtil.getSessionFactory().openSession();
        Transaction oTransaction = oSession.beginTransaction();
        try {
            Synonym oSynonym = ISSOHelpers.fetchSynonym(sSynonym, oSession,
                    oTransaction);
            if (oSynonym.getId() != null) {
                String sGINU = null;
                Synonym oGINU = oSynonym.getGlobalINumber();
                if (oGINU == null) {
                    sGINU = sSynonym;
                } else {
                    sGINU = oGINU.getSynonym();
                }
                logger.info("getGlobalINumberBySynonym() : exit return GINU:"
                        + sGINU);
                return sGINU;
            } else {
                throw new IServiceException(logger, 2034);
            }
        } finally {
            oSession.close();
        }
    }

    /**
     * Gets the information about the given ibroker
     * 
     * @param ibrokerName
     *            Name of the ibroker
     * @return Map having Broker information
     * @throws IServiceException
     */
    public static Map getIBrokerData(String ibrokerName)
            throws IServiceException {
        logger.info("getIBrokerData(): entry with data:BrokerName="
                + ibrokerName);
        Map oDataMap = null;
        Session oHibernateSession = null;
        Transaction oHibernateTran = null;
        try {
            oHibernateSession = HibernateUtil.getSessionFactory().openSession();
            oHibernateSession.beginTransaction();
            IBroker oIBroker = ISSOHelpers.fetchIBroker(ibrokerName,
                    oHibernateSession, oHibernateTran);
            oDataMap = oIBroker.getBrokerData();
            logger.info("getIBrokerData(): exit");
            return oDataMap;
        } catch (Exception e) {
            // TODO
            logger.warn("getIBrokerData(): Exception" + e.getMessage());
        } finally {
            if (oHibernateSession != null) {
                oHibernateSession.close();
            }
        }
        return oDataMap;
    }

    /**
     * Return the Ibroker object having links to contact and forwarding service
     * 
     * @param ibrokerName
     *            Name of the ibroker
     * @return IBroker object
     * @throws IServiceException
     */
    public static IBroker getIBrokerInfo(String ibrokerName)
            throws IServiceException {
        logger.info("getIBrokerInfo(): entry with data:BrokerName="
                + ibrokerName);
        IBroker oIBroker = null;
        Session oHibernateSession = null;
        Transaction oHibernateTran = null;
        try {
            oHibernateSession = HibernateUtil.getSessionFactory().openSession();
            oHibernateSession.beginTransaction();
            oIBroker = ISSOHelpers.fetchIBroker(ibrokerName, oHibernateSession,
                    oHibernateTran);
            logger.info("getIBrokerInfo(): exit");
            return oIBroker;
        } catch (Exception e) {
            logger.warn("getIBrokerInfo(): Exception : " + e.getMessage());
        } finally {
            if (oHibernateSession != null) {
                oHibernateSession.close();
            }
        }
        return oIBroker;
    }

    /**
     * Used to get the object of the given ibroker
     * 
     * @param ibrokerName
     * @return IBroker object
     * @throws IServiceException
     */
    public static IBroker getIBroker(String ibrokerName)
            throws IServiceException {
        logger.info("getIBroker(): entry with data:BrokerName=" + ibrokerName);
        IBroker oIBroker = null;
        Session oHibernateSession = null;
        Transaction oHibernateTran = null;
        try {
            oHibernateSession = HibernateUtil.getSessionFactory().openSession();
            oHibernateSession.beginTransaction();
            oIBroker = ISSOHelpers.fetchIBroker(ibrokerName, oHibernateSession,
                    oHibernateTran);
            logger.info("getIBroker(): exit");
            return oIBroker;
        } catch (Exception e) {
            logger.warn("getIBroker(): Exception : " + e.getMessage());
        } finally {
            if (oHibernateSession != null) {
                oHibernateSession.close();
            }
        }
        return oIBroker;
    }
}